package com.springboot.study.consumer;
import com.springboot.study.config.WorkQueueConfig; // 导入自定义的队列配置类
import org.springframework.amqp.rabbit.annotation.RabbitListener; // 监听 RabbitMQ 队列消息
import org.springframework.amqp.support.AmqpHeaders; // 提供 RabbitMQ 消息头常量
import org.springframework.messaging.handler.annotation.Header; // 用于获取消息头参数
import org.springframework.stereotype.Component; // 将类注册为 Spring Bean
import com.rabbitmq.client.Channel; // RabbitMQ 的 Channel 类
import java.io.IOException;
/*
* 说明：
*   @RabbitListener：监听指定队列的消息。
*   worker1、worker2：两个不同的消费者，分别模拟慢速和快速处理。
*   Channel + deliveryTag：用于手动确认消息（手动 ACK）。
*   basicAck(deliveryTag, false)：确认消息已处理完成。
*   basicNack(deliveryTag, false, true)：拒绝消息，并将其重新放回队列。
*   Thread.sleep(...)：模拟任务执行耗时。
*
* */
/**
 * 工作队列模式消费者组件
 * 工作队列模式用于平衡多个消费者之间的消息处理负载，
 * 适合处理耗时任务，通过多个消费者并行处理提高效率。
 */
@Component
public class WorkConsumer {
    /**
     * 工作者1处理方法
     * @param message 接收到的消息内容
     * @param channel RabbitMQ通道对象，用于手动ACK/NACK等操作
     * @param deliveryTag 消息交付标签，用于标识消息的唯一性
     */
    @RabbitListener(queues = WorkQueueConfig.WORK_QUEUE) // 监听配置中定义的工作队列
    public void worker1(String message, Channel channel,
                        @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        try {
            // 1. 处理接收到的消息
            System.out.println("工作者1处理：" + message);

            // 2. 模拟耗时任务（2秒），表示处理速度较慢
            Thread.sleep(2000);

            // 3. 处理成功后手动确认消息
            // 参数说明：
            // deliveryTag - 消息标签
            // multiple - 是否批量确认（false表示只确认当前消息）
            channel.basicAck(deliveryTag, false);

        } catch (Exception e) {
            // 处理过程中发生异常
            handleError(channel, deliveryTag);
        }
    }

    /**
     * 工作者2处理方法
     *
     * @param message 接收到的消息内容
     * @param channel RabbitMQ通道对象
     * @param deliveryTag 消息交付标签
     */
    @RabbitListener(queues = WorkQueueConfig.WORK_QUEUE) // 同样监听工作队列
    public void worker2(String message, Channel channel,
                        @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        try {
            // 1. 处理接收到的消息
            System.out.println("工作者2处理：" + message);

            // 2. 模拟耗时任务（1秒），表示处理速度较快
            Thread.sleep(1000);

            // 3. 处理成功后手动确认消息
            channel.basicAck(deliveryTag, false);

        } catch (Exception e) {
            // 处理过程中发生异常
            handleError(channel, deliveryTag);
        }
    }

    /**
     * 错误处理方法
     *
     * 当消息处理失败时，拒绝消息并重新入队
     *
     * @param channel RabbitMQ通道对象
     * @param deliveryTag 消息交付标签
     */
    private void handleError(Channel channel, long deliveryTag) {
        try {
            /**
             * 拒绝消息并选择是否重新入队
             * 参数说明：
             * deliveryTag - 消息标签
             * multiple - 是否批量拒绝
             * requeue - 是否重新放入队列（true表示重新入队）
             *
             * 注意：重新入队可能会导致消息重复处理，需要确保业务逻辑的幂等性
             */
            channel.basicNack(deliveryTag, false, true);
        } catch (IOException e) {
            // 记录错误日志
            e.printStackTrace();
        }
    }
}
